/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "config_reader/ConfigIniReader.h"
#include "common/EnvVarManager.h"
#include "protect_engines/hyperv/api/powershell/model/GetVMVolumesModel.h"
#include "HyperVResourceAccess.h"
using namespace HyperVPlugin::Utils;

namespace {
const std::string BIN_DIR = Module::EnvVarManager::GetInstance()->GetAgentHomePath() +
    "\\DataBackup\\ProtectClient\\Plugins\\VirtualizationPlugin\\bin";
const std::string EXECUTOR_NAME = "Executor.ps1";
const std::string CMD_TYPE_CHECK_CONNECTION_SCVMM = "CheckSCConnection";
const std::string CMD_TYPE_CHECK_CONNECTION_HOST = "CheckHostConnection";
const std::string CMD_TYPE_CHECK_CONNECTION_CLUSTER = "CheckClusterConnection";
const std::string CMD_TYPE_LIST_CLUSTER = "ListCluster";
const std::string CMD_TYPE_LIST_CLUSTER_HOST = "ListClusterHost";
const std::string CMD_TYPE_LIST_HOST = "ListHost";
const std::string CMD_TYPE_LIST_VM = "ListVM";
const std::string CMD_TYPE_LIST_DISK = "ListDisk";
const std::string CMD_TYPE_LIST_DIRECTORY = "ListDirectory";
const std::string CMD_TYPE_LIST_IP_ADDRESS = "ListIpAddress";
const std::string CMD_TYPE_LIST_VM_IP_ADDRESS = "ListVMIpAddress";
const DWORD TIMEOUT_DEFAULT = 300;
const int64_t WIN_SERVICE_FAILED = 200;
const int64_t ACTION_ERROR = 200;
const std::string RESOURCE_TYPE = "Hyper-V";
const std::string RESOURCE_SUBTYPE_CLUSTER = "HyperV.Cluster";
const std::string RESOURCE_SUBTYPE_HOST = "HyperV.Host";
const std::string RESOURCE_SUBTYPE_VM = "HyperV.VM";
const std::string RESOURCE_SUBTYPE_DISK = "HyperV.Disk";
const std::string RESOURCE_SUBTYPE_DIRECTORY = "HyperV.Directory";
const std::string CONDITION_UUID = "uuid";
const std::string APP_EXTEND_FQDN = "FQDN";
const std::string APP_EXTEND_PAGENO = "PageNo";
const std::string APP_EXTEND_PAGESIZE = "PageSize";
const std::string UNKNOWN = "unknown";
constexpr int64_t HYPERV_SERVICE_FAILED = 1577213575;
constexpr int64_t HYPERV_AUTH_FAILED = 1077949061;
}

namespace HyperVPlugin {
std::map<std::string, bool> g_listTaskMap {};
std::mutex g_listLock;
std::condition_variable g_listCnv;

HyperVResourceAccess::HyperVResourceAccess(const ApplicationEnvironment &appEnv, const Application &application)
    : m_appEnv(appEnv), m_application(application)
{}

HyperVResourceAccess::HyperVResourceAccess(const ApplicationEnvironment &appEnv, const QueryByPage &pageInfo)
    : m_appEnv(appEnv), m_condition(pageInfo)
{
    m_pageNo = m_condition.pageNo;
    m_pageSize = m_condition.pageSize;
}

HyperVResourceAccess::~HyperVResourceAccess() {}

void HyperVResourceAccess::GetParentInfo(ApplicationResource &appResource)
{
    if (m_isParentInfoExist) {
        appResource.__set_parentId(m_parentId);
        appResource.__set_parentName(m_parentName);
    } else {
        appResource.__set_parentId(m_application.id);
        appResource.__set_parentName(m_application.name);
    }
}

int32_t HyperVResourceAccess::CheckSCVMMConnection(ActionResult &returnValue)
{
    LOGGUARD("");
    m_execaller.SetTargetHost(m_appEnv.endpoint);
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_SCVMM);
    ActionResultResAcc result = Executor<ActionResultResAcc>(CMD_TYPE_CHECK_CONNECTION_SCVMM);
    if (result.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", result.m_code);
        if (result.m_bodyErr == WIN_SERVICE_FAILED) {
            returnValue.__set_code(ACTION_ERROR);
            returnValue.__set_bodyErr(HYPERV_SERVICE_FAILED);
            returnValue.__set_message(result.m_message);
            std::vector<std::string> errParam {"SCVMM"};
            returnValue.__set_bodyErrParams(errParam);
            return result.m_code;
        }
        returnValue.__set_code(ACTION_ERROR);
        returnValue.__set_bodyErr(HYPERV_AUTH_FAILED);
        returnValue.__set_message(result.m_message);
        return result.m_code;
    } else {
        INFOLOG("Check scvmm connection success.");
    }

    returnValue.__set_code(result.m_code);
    returnValue.__set_bodyErr(result.m_bodyErr);
    returnValue.__set_message(result.m_message);
    return result.m_code;
}

int32_t HyperVResourceAccess::CheckClusterConnection(ActionResult &returnValue)
{
    LOGGUARD("");
    m_execaller.SetTargetHost(m_appEnv.endpoint);
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_FO_CLUSTER);
    ActionResultResAcc result = Executor<ActionResultResAcc>(CMD_TYPE_CHECK_CONNECTION_CLUSTER);
    if (result.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", result.m_code);
        if (result.m_bodyErr == WIN_SERVICE_FAILED) {
            returnValue.__set_code(ACTION_ERROR);
            returnValue.__set_bodyErr(HYPERV_SERVICE_FAILED);
            returnValue.__set_message(result.m_message);
            std::vector<std::string> errParam {"Failover_Cluster"};
            returnValue.__set_bodyErrParams(errParam);
            return result.m_code;
        }
        returnValue.__set_code(ACTION_ERROR);
        returnValue.__set_bodyErr(HYPERV_AUTH_FAILED);
        returnValue.__set_message(result.m_message);
        return result.m_code;
    } else {
        INFOLOG("Check scvmm connection success.");
    }

    returnValue.__set_code(result.m_code);
    returnValue.__set_bodyErr(result.m_bodyErr);
    returnValue.__set_message(result.m_message);
    return result.m_code;
}

int32_t HyperVResourceAccess::CheckHostConnection(ActionResult &returnValue)
{
    LOGGUARD("");
    m_execaller.SetTargetHost(GetExtendValue(APP_EXTEND_FQDN));
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_HOST);
    ActionResultResAcc result = Executor<ActionResultResAcc>(CMD_TYPE_CHECK_CONNECTION_HOST);
    if (result.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", result.m_code);
        returnValue.__set_code(ACTION_ERROR);
        returnValue.__set_bodyErr(HYPERV_SERVICE_FAILED);
        std::vector<std::string> errParam {"HyperV"};
        returnValue.__set_bodyErrParams(errParam);
        return result.m_code;
    } else {
        INFOLOG("Check host connection success.");
        returnValue.__set_bodyErr(result.m_bodyErr);
    }

    returnValue.__set_code(result.m_code);
    returnValue.__set_message(result.m_message);
    return result.m_code;
}

int32_t HyperVResourceAccess::GetClusterList(ResourceResultByPage &page)
{
    LOGGUARD("");
    HyperVClusterList hvClusterList;
    m_execaller.SetTargetHost(m_appEnv.endpoint);
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_SCVMM);
    ActionResultResAcc result = Executor<HyperVClusterList>(CMD_TYPE_LIST_CLUSTER, hvClusterList);
    if (result.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", result.m_code);
        return FAILED;
    }

    for (const HyperVClusterInfo &clusterInfo : hvClusterList.m_clusterList) {
        ApplicationResource appResource;
        appResource.__set_type(RESOURCE_TYPE);
        appResource.__set_subType(RESOURCE_SUBTYPE_CLUSTER);
        appResource.__set_id(clusterInfo.m_id);
        appResource.__set_name(clusterInfo.m_name);
        GetParentInfo(appResource);
        page.items.push_back(appResource);
    }
    page.__set_pageNo(m_pageNo);
    page.__set_pageSize(page.items.size());
    page.__set_total(page.items.size());

    INFOLOG("Get host list success.");
    return SUCCESS;
}

int32_t HyperVResourceAccess::GetClusterHostList(ResourceResultByPage &page)
{
    LOGGUARD("");
    HyperVNodeList hvNodeList;
    m_execaller.SetTargetHost(m_appEnv.endpoint);
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_FO_CLUSTER);
    ActionResultResAcc result = Executor<HyperVNodeList>(CMD_TYPE_LIST_CLUSTER_HOST, hvNodeList);
    if (result.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", result.m_code);
        return FAILED;
    }
    for (const HyperVNodeInfo &nodeInfo : hvNodeList.m_hostList) {
        ApplicationResource appResource;
        appResource.__set_type(RESOURCE_TYPE);
        appResource.__set_subType(RESOURCE_SUBTYPE_HOST);
        appResource.__set_id(nodeInfo.m_id);
        appResource.__set_name(nodeInfo.m_name);
        GetParentInfo(appResource);

        std::string extendInfoStr;
        HyperVHostExtendInfo extendInfo;
        extendInfo.m_state = nodeInfo.m_overallState;
        extendInfo.m_status = nodeInfo.m_overallState == "Up" ? "OK" : "NeedsAttention";
        extendInfo.m_hostCluster = nodeInfo.m_hostCluster;
        extendInfo.m_fQDN = nodeInfo.m_fQDN;
        std::string ipAddress = nodeInfo.m_ips;
        if (!ipAddress.empty()) {
            ipAddress.pop_back();
        }
        extendInfo.m_ipList = ipAddress;
        if (!Module::JsonHelper::StructToJsonString(extendInfo, extendInfoStr)) {
            ERRLOG("Tranform extendInfo to string failed.");
            return FAILED;
        }
        appResource.__set_extendInfo(extendInfoStr);
        page.items.push_back(appResource);
    }
    page.__set_pageNo(m_pageNo);
    page.__set_pageSize(page.items.size());
    page.__set_total(page.items.size());

    INFOLOG("Get host list success.");
    return SUCCESS;
}

int32_t HyperVResourceAccess::GetHostList(ResourceResultByPage &page)
{
    LOGGUARD("");
    HyperVHostList hvHostList;
    m_execaller.SetTargetHost(m_appEnv.endpoint);
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_SCVMM);
    ActionResultResAcc result = Executor<HyperVHostList>(CMD_TYPE_LIST_HOST, hvHostList);
    if (result.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", result.m_code);
        return FAILED;
    }

    for (const HyperVHostInfo &hostInfo : hvHostList.m_hostList) {
        ApplicationResource appResource;
        appResource.__set_type(RESOURCE_TYPE);
        appResource.__set_subType(RESOURCE_SUBTYPE_HOST);
        appResource.__set_id(hostInfo.m_id);
        appResource.__set_name(hostInfo.m_name);
        GetParentInfo(appResource);
        if (m_isParentInfoExist && (hostInfo.m_hostCluster != appResource.parentName)) {
            INFOLOG("Host cluster(%s) not belong this cluster(%s), skip.",
                hostInfo.m_hostCluster.c_str(), appResource.parentName.c_str());
            continue;
        }

        std::string extendInfoStr;
        HyperVHostExtendInfo extendInfo;
        extendInfo.m_state = hostInfo.m_overallState;
        extendInfo.m_status = hostInfo.m_overallState;
        extendInfo.m_hostCluster = hostInfo.m_hostCluster;
        extendInfo.m_fQDN = hostInfo.m_fQDN;
        std::string ipAddress = Module::CMpString::StrReplace(hostInfo.m_ips, " ", ",");
        DBGLOG("Ip after:%s", ipAddress.c_str());
        extendInfo.m_ipList = ipAddress;
        if (!Module::JsonHelper::StructToJsonString(extendInfo, extendInfoStr)) {
            ERRLOG("Tranform extendInfo to string failed.");
            return FAILED;
        }
        appResource.__set_extendInfo(extendInfoStr);
        page.items.push_back(appResource);
    }
    page.__set_pageNo(m_pageNo);
    page.__set_pageSize(page.items.size());
    page.__set_total(page.items.size());

    INFOLOG("Get host list success.");
    return SUCCESS;
}

int32_t HyperVResourceAccess::GetIpAddress(const std::string &hostName, std::string &ipAddress)
{
    HyperVIpList ipList;
    Json::Value param;
    m_execaller.SetTargetHost(m_appEnv.endpoint);
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_SCVMM);
    param["HostName"] = hostName;
    ActionResultResAcc ipResult = Executor<HyperVIpList>(CMD_TYPE_LIST_IP_ADDRESS, ipList, param);
    if (ipResult.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", ipResult.m_code);
        return FAILED;
    }
    for (const auto &ipInfo : ipList.m_ipList) {
        INFOLOG("Get ip address: %s.", ipInfo.m_iPAddressToString.c_str());
        ipAddress = ipInfo.m_iPAddressToString.empty() ? ipAddress :
            ipAddress + ipInfo.m_iPAddressToString + ",";
    }
    if (!ipAddress.empty()) {
        ipAddress.pop_back();
    }
    return SUCCESS;
}

int32_t HyperVResourceAccess::GetVMIpAddress(ResourceResultByPage &page)
{
    Json::Reader conditionReader;
    Json::Value conditionJson;
    if (!conditionReader.parse(m_condition.conditions, conditionJson)) {
        ERRLOG("Failed to read condition.");
        return FAILED;
    }
    if (!conditionJson.isMember(APP_EXTEND_FQDN) || !conditionJson.isMember(CONDITION_UUID)) {
        ERRLOG("No source key targetType.");
        return FAILED;
    }
    HyperVVMIpList ipList;
    Json::Value param;
    m_execaller.SetTargetHost(conditionJson[APP_EXTEND_FQDN].asString());
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_HOST);
    std::string vmId = conditionJson[CONDITION_UUID].asString();
    param["VMId"] = vmId;
    ActionResultResAcc ipResult = Executor<HyperVVMIpList>(CMD_TYPE_LIST_VM_IP_ADDRESS, ipList, param);
    if (ipResult.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", ipResult.m_code);
        return FAILED;
    }
    std::string ipAddress;
    for (const auto &ip : ipList.m_ipList) {
        INFOLOG("Get ip address: %s.", ip.c_str());
        ipAddress = ip.empty() ? ipAddress :
            ipAddress + ip + ",";
    }
    if (!ipAddress.empty()) {
        ipAddress.pop_back();
    }
    ApplicationResource appResource;
    appResource.__set_type(RESOURCE_TYPE);
    appResource.__set_subType(RESOURCE_SUBTYPE_VM);
    appResource.__set_id(vmId);
    appResource.__set_name(vmId);
    Json::Value extParam;
    Json::FastWriter writer;
    extParam["ipAddress"] = ipAddress;
    appResource.__set_extendInfo(writer.write(extParam));
    page.items.push_back(appResource);
    return SUCCESS;
}

void HyperVResourceAccess::CheckTask()
{
    INFOLOG("Check Start.");
    std::unique_lock<std::mutex> lock(g_listLock);
    bool flag {false};
    if (g_listTaskMap.count(m_requestId) == 0) {
        return;
    }
    while (g_listTaskMap[m_requestId]) {
        g_listCnv.wait(lock);
    }
    g_listTaskMap[m_requestId] = true;
    INFOLOG("Check End.");
}

void HyperVResourceAccess::EndTask()
{
    INFOLOG("End Start.");
    std::unique_lock<std::mutex> lock(g_listLock);
    g_listTaskMap[m_requestId] = false;
    g_listCnv.notify_all();
    INFOLOG("End End.");
}

int32_t HyperVResourceAccess::GetVMList(ResourceResultByPage &page)
{
    CheckTask();
    HyperVVMList hvVMList;
    Json::Value param;
    m_execaller.SetTargetHost(GetExtendValue(APP_EXTEND_FQDN));
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_HOST);
    ActionResultResAcc result = Executor<HyperVVMList>(CMD_TYPE_LIST_VM, hvVMList, param);
    if (result.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", result.m_code);
        return FAILED;
    }
    for (const HyperVVMInfo &vmInfo : hvVMList.m_vmList) {
        if (vmInfo.m_vmName == "") {
            continue;
        }
        ApplicationResource appResource;
        appResource.__set_type(RESOURCE_TYPE);
        appResource.__set_subType(RESOURCE_SUBTYPE_VM);
        appResource.__set_id(vmInfo.m_vmId);
        appResource.__set_name(vmInfo.m_vmName);
        GetParentInfo(appResource);

        std::string extendInfoStr;
        HyperVVMExtendInfo extendInfo;
        std::string ipAddress = Module::CMpString::StrReplace(vmInfo.m_ips, " ", ",");
        DBGLOG("Vmip after:%s", ipAddress.c_str());
        extendInfo.m_ipList = ipAddress;
        extendInfo.m_state = vmInfo.m_state;
        extendInfo.m_status = vmInfo.m_state;
        extendInfo.m_version = vmInfo.m_version;
        extendInfo.m_generation = vmInfo.m_generation;
        extendInfo.m_configurationLocation = vmInfo.m_configurationLocation;
        extendInfo.m_checkpointFileLocation = vmInfo.m_checkpointFileLocation;
        extendInfo.m_osType = UNKNOWN;
        if (!Module::JsonHelper::StructToJsonString(extendInfo, extendInfoStr)) {
            ERRLOG("Tranform extendInfo to string failed.");
            return FAILED;
        }
        appResource.__set_extendInfo(extendInfoStr);

        DBGLOG("VMName: %s", vmInfo.m_vmName.c_str());
        page.items.push_back(appResource);
    }
    page.__set_pageNo(m_pageNo);
    page.__set_pageSize(page.items.size());
    page.__set_total(page.items.size());
    EndTask();
    INFOLOG("Get vm list success.");
    return SUCCESS;
}

int32_t HyperVResourceAccess::GetDiskList(ResourceResultByPage &page)
{
    CheckTask();
    Json::Value param;
    param["VMId"] = m_application.id;
    GetVMVolumesResponse hvDiskList;
    m_execaller.SetTargetHost(GetExtendValue(APP_EXTEND_FQDN));
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_HOST);
    ActionResultResAcc result = Executor<GetVMVolumesResponse>(CMD_TYPE_LIST_DISK, hvDiskList, param);
    if (result.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", result.m_code);
        return FAILED;
    }

    for (VolumeInfo &diskInfo : hvDiskList.m_diskList) {
        ApplicationResource appResource;
        appResource.__set_type(RESOURCE_TYPE);
        appResource.__set_subType(RESOURCE_SUBTYPE_DISK);
        std::string uuidLowerCase = diskInfo.m_diskIdentifier;
        std::transform(uuidLowerCase.begin(), uuidLowerCase.end(), uuidLowerCase.begin(), ::tolower);
        diskInfo.m_diskIdentifier = uuidLowerCase;
        appResource.__set_id(uuidLowerCase);
        appResource.__set_parentId(diskInfo.m_vmId);
        auto pos = diskInfo.m_path.find_last_of('\\');
        if (pos != std::string::npos) {
            appResource.__set_name(diskInfo.m_path.substr(pos + 1));
        }
        if (diskInfo.m_isPhysicalHardDisk) {
            appResource.__set_name(diskInfo.m_path);
        }
        std::string extendInfoStr;
        VolumeExtendInfo extendInfo(diskInfo);
        if (!Module::JsonHelper::StructToJsonString(extendInfo, extendInfoStr)) {
            ERRLOG("Tranform extendInfo to string failed.");
            return FAILED;
        }
        INFOLOG("Disk extendInfoStr : %s", extendInfoStr.c_str());
        appResource.__set_extendInfo(extendInfoStr);
        page.items.push_back(appResource);
    }
    page.__set_pageNo(m_pageNo);
    page.__set_pageSize(page.items.size());
    page.__set_total(page.items.size());
    EndTask();
    INFOLOG("Get disk list success.");
    return SUCCESS;
}

int32_t HyperVResourceAccess::GetDirectoryList(ResourceResultByPage &page)
{
    INFOLOG("----------------GetDirectoryList-----------------");
    Json::Value param;
    std::string extendInfo = "{\"Page\": 1,\"Size\": 10,\"FilePath\": \"C:/\"}";
    if (!Module::JsonHelper::JsonStringToJsonValue(extendInfo, param)) {
        ERRLOG("Trans m_application extend info to json value failed");
        return FAILED;
    }
    if (!param["Page"].isInt() || !param["Size"].isInt()) {
        ERRLOG("Page or Size format is incorrect, need int.");
        return FAILED;
    }
    if (param["Page"].asInt() < 0 || param["Size"].asInt() < 0) {
        ERRLOG("Page or Size less than zero.");
        return FAILED;
    }

    HyperVDirectoryList hvDirectoryList;
    m_execaller.SetTargetHost(GetExtendValue(APP_EXTEND_FQDN));
    m_execaller.SetTargetType(CMD_RUNNING_TARGET::TYPE_HOST);
    ActionResultResAcc result = Executor<HyperVDirectoryList>(CMD_TYPE_LIST_DIRECTORY, hvDirectoryList, param);
    if (result.m_code != SUCCESS) {
        ERRLOG("Run Executor failed, code=%d", result.m_code);
        return FAILED;
    }

    for (HyperVDirectoryInfo &directoryInfo : hvDirectoryList.m_directoryList) {
        ApplicationResource appResource;
        appResource.__set_type(RESOURCE_TYPE);
        appResource.__set_subType(RESOURCE_SUBTYPE_DIRECTORY);
        appResource.__set_id("");
        GetParentInfo(appResource);
        appResource.__set_name(directoryInfo.m_name);
        if (directoryInfo.m_type.find("d") > 0) {
            directoryInfo.m_type = "directory";
        } else {
            directoryInfo.m_type = "file";
        }
        std::string extendInfoStr;
        if (!Module::JsonHelper::StructToJsonString(directoryInfo, extendInfoStr)) {
            ERRLOG("Tranform extendInfo to string failed.");
            return FAILED;
        }
        INFOLOG("Directory extendInfoStr : %s", extendInfoStr.c_str());
        appResource.__set_extendInfo(extendInfoStr);

        page.items.push_back(appResource);
    }
    page.__set_total(hvDirectoryList.m_total);

    INFOLOG("Get directory list success.");
    return SUCCESS;
}

template <typename T>
ActionResultResAcc HyperVResourceAccess::Executor(const std::string &command, T &res, const Json::Value &param)
{
    LOGGUARD("");
    Param prm;
    prm.scriptDir = BIN_DIR;
    prm.timeout = TIMEOUT_DEFAULT;
    prm.cmdType = command;
    prm.scriptName = EXECUTOR_NAME;
    prm.userName = m_appEnv.auth.authkey;
    prm.password = m_appEnv.auth.authPwd;
    prm.requestId = m_requestId;

    prm.param = param;
    prm.param[APP_EXTEND_PAGENO] = m_pageNo;
    prm.param[APP_EXTEND_PAGESIZE] = m_pageSize;

    Json::Value result;
    ActionResultResAcc actionResult;
    int retRes = m_execaller.Execute(prm, result);
    if (retRes != SUCCESS) {
        Module::JsonHelper::JsonValueToStruct(result, actionResult);
        ERRLOG("Run executor failed, retRes=%d, code:%d", retRes, actionResult.m_code);
        return actionResult;
    }
    DBGLOG("Call execute command success.");
    if (!CheckResultValid(result)) {
        ERRLOG("Get empty result.");
        Module::JsonHelper::JsonValueToStruct(result, actionResult);
        return actionResult;
    }
    Module::JsonHelper::JsonValueToStruct(result, res);
    return actionResult;
}

bool HyperVResourceAccess::CheckResultValid(const Json::Value &result)
{
    if (result.empty() || !result.isMember("result") || !result["result"].isArray() ||
        result["result"].size() <= 0) {
        return false;
    }
    return true;
}

std::string HyperVResourceAccess::GetExtendValue(const std::string &key)
{
    Json::Value jVal;
    if (!Module::JsonHelper::JsonStringToJsonValue(m_appEnv.extendInfo, jVal) || !jVal.isMember(key)) {
        return std::string();
    }
    return jVal[key].asString();
}

}